package org.epidroid.epidroid;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class ConfigureIitWifi extends Activity {

	/**
	 * Pattern of a login.
	 */
	private static final Pattern _login = Pattern
			.compile("([a-zA-Z-]{2,6}_\\S)(\\s*)");

	private static final String INT_PRIVATE_KEY = "private_key";
	private static final String INT_PHASE2 = "phase2";
	private static final String INT_PASSWORD = "password";
	private static final String INT_IDENTITY = "identity";
	private static final String INT_EAP = "eap";
	private static final String INT_CLIENT_CERT = "client_cert";
	private static final String INT_CA_CERT = "ca_cert";
	private static final String INT_ANONYMOUS_IDENTITY = "anonymous_identity";
	final String INT_ENTERPRISEFIELD_NAME = "android.net.wifi.WifiConfiguration$EnterpriseField";

	private final static int SUCCESS = 0;
	private final static int UNKNOWN_ERROR = 1;
	private final static int CANT_ENABLE_WIFI = 2;
	private final static int CANT_ADD_NETWORK = 3;
	private final static int CANT_SAVE_NETWORK = 4;
	private final static int LOGIN_NOT_WELL_FORMED = 5;
	private final static int JELLY_BEAN_ERROR = 6; // more details : http://code.google.com/p/android/issues/detail?id=34212

	private final static int errors[] = { R.string.success,
			R.string.unknown_error, R.string.cant_enable_wifi,
			R.string.cant_add_network, R.string.cant_save_network,
			R.string.cant_enable_network, R.string.login_not_well_formed,
			R.string.jelly_bean_bug};

	private WifiManager wifiManager = null;
	private int network_id = 0;

	private SharedPreferences _prefs = null;
	private EditText _editLogin = null;
	private EditText _editPass = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.configure_wifi);

		_prefs = PreferenceManager.getDefaultSharedPreferences(this);

		String login = _prefs.getString("login", "");
		String pass = _prefs.getString("pass", "");

		_editLogin = (EditText) findViewById(R.id.entry_username);
		_editPass = (EditText) findViewById(R.id.entry_password);

		_editLogin.setText(login);
		_editPass.setText(pass);
	}

	public void getConnected(View v) {
		wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		WifiConfiguration iitWifi = null;
		for (WifiConfiguration conf : wifiManager.getConfiguredNetworks()) {
			if (conf.SSID.equals("\"iit-wifi\"")) {
				iitWifi = conf;
			}
		}

		if (iitWifi == null) {
			launchProcess();
		} else {
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage(R.string.wifi_already_exists)
					.setCancelable(true)
					.setPositiveButton(R.string.continue_,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int id) {
									launchProcess();
								}
							})
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int id) {
									dialog.cancel();
								}
							});
			AlertDialog alert = builder.create();
			alert.show();
		}
	}

	private void launchProcess() {
		String login = _editLogin.getText().toString();
		String password = _editPass.getText().toString();

		Matcher match = _login.matcher(login);
		int res = -1;
		int _pos = login.indexOf('_');

		if (match.find() && (login.length() - _pos) == 2)
			res = addNetwork(login, password);
		else
			res = LOGIN_NOT_WELL_FORMED;
		if (0 != network_id) {
			wifiManager.startScan();
		}
		Toast.makeText(this, errors[res], Toast.LENGTH_LONG).show();
	}

	private int addNetwork(String user, String password) {

		WifiConfiguration iitWifi = new WifiConfiguration();
		iitWifi.BSSID = null;
		iitWifi.SSID = "\"iit-wifi\"";
		iitWifi.hiddenSSID = true;
		iitWifi.preSharedKey = null;

		iitWifi.status = WifiConfiguration.Status.DISABLED;
		iitWifi.priority = 40;

		iitWifi.allowedKeyManagement.clear();
		iitWifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
		iitWifi.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);

		iitWifi.allowedProtocols.clear();
		iitWifi.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
		iitWifi.allowedProtocols.set(WifiConfiguration.Protocol.RSN);

		iitWifi.allowedPairwiseCiphers.clear();
		iitWifi.allowedPairwiseCiphers
				.set(WifiConfiguration.PairwiseCipher.CCMP);
		iitWifi.allowedPairwiseCiphers
				.set(WifiConfiguration.PairwiseCipher.TKIP);

		iitWifi.allowedGroupCiphers.clear();
		iitWifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
		iitWifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
		iitWifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
		iitWifi.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);

		iitWifi.allowedAuthAlgorithms.clear();

		// From HERE
		// http://stackoverflow.com/questions/4374862/how-to-programatically-create-and-read-wep-eap-wifi-configurations-in-android/4375874#4375874
		try {
			// Let the magic start
			@SuppressWarnings("rawtypes")
			Class[] wcClasses = WifiConfiguration.class.getClasses();
			// null for overzealous java compiler
			@SuppressWarnings("rawtypes")
			Class wcEnterpriseField = null;

			for (@SuppressWarnings("rawtypes")
			Class wcClass : wcClasses)
				if (wcClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
					wcEnterpriseField = wcClass;
					break;
				}
			boolean noEnterpriseFieldType = false;
			if (wcEnterpriseField == null) {
				noEnterpriseFieldType = true; // Cupcake/Donut access enterprise
												// settings directly
			}

			Field wcefAnonymousId = null, wcefCaCert = null, wcefClientCert = null, wcefEap = null, wcefIdentity = null, wcefPassword = null, wcefPhase2 = null, wcefPrivateKey = null;
			Field[] wcefFields = WifiConfiguration.class.getFields();
			// Dispatching Field vars
			for (Field wcefField : wcefFields) {
				if (wcefField.getName().equals(INT_ANONYMOUS_IDENTITY))
					wcefAnonymousId = wcefField;
				else if (wcefField.getName().equals(INT_CA_CERT))
					wcefCaCert = wcefField;
				else if (wcefField.getName().equals(INT_CLIENT_CERT))
					wcefClientCert = wcefField;
				else if (wcefField.getName().equals(INT_EAP))
					wcefEap = wcefField;
				else if (wcefField.getName().equals(INT_IDENTITY))
					wcefIdentity = wcefField;
				else if (wcefField.getName().equals(INT_PASSWORD))
					wcefPassword = wcefField;
				else if (wcefField.getName().equals(INT_PHASE2))
					wcefPhase2 = wcefField;
				else if (wcefField.getName().equals(INT_PRIVATE_KEY))
					wcefPrivateKey = wcefField;
			}

			Method wcefSetValue = null;
			if (!noEnterpriseFieldType) {
				for (Method m : wcEnterpriseField.getMethods())
					if (m.getName().trim().equals("setValue"))
						wcefSetValue = m;
			}
			
			if ((wcefPrivateKey == null)) {
				return JELLY_BEAN_ERROR;
			}
			
			String ENTERPRISE_EAP = "PEAP";
			String ENTERPRISE_PHASE2 = ""; // MSCHAPV2
			String ENTERPRISE_ANON_IDENT = "";
			String ENTERPRISE_CA_CERT = "";
			String ENTERPRISE_PRIV_KEY = "";
			String ENTERPRISE_CLIENT_CERT = "";
			/* EAP Method */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefEap.get(iitWifi), ENTERPRISE_EAP);

			/* EAP Phase 2 Authentication */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPhase2.get(iitWifi), ENTERPRISE_PHASE2);

			/* EAP Anonymous Identity */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefAnonymousId.get(iitWifi),
						ENTERPRISE_ANON_IDENT);

			/* EAP CA Certificate */
			if (!noEnterpriseFieldType)
				wcefSetValue
						.invoke(wcefCaCert.get(iitWifi), ENTERPRISE_CA_CERT);

			/* EAP Private key */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPrivateKey.get(iitWifi),
						ENTERPRISE_PRIV_KEY);

			/* EAP Identity */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefIdentity.get(iitWifi), user);

			/* EAP Password */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPassword.get(iitWifi), password);

			/* EAp Client certificate */
			if (!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefClientCert.get(iitWifi),
						ENTERPRISE_CLIENT_CERT);

		} catch (Exception e) {
			e.printStackTrace();
			return UNKNOWN_ERROR;
		}

		if (!wifiManager.setWifiEnabled(true))
			return CANT_ENABLE_WIFI;
		if ((network_id = wifiManager.addNetwork(iitWifi)) == -1)
			return CANT_ADD_NETWORK;
		if (!wifiManager.saveConfiguration())
			return CANT_SAVE_NETWORK;
		if (wifiManager.enableNetwork(network_id, true))
			return SUCCESS;// CANT_ENABLE_NETWORK;

		return SUCCESS;
	}
}
